package com.tanhua.server.service;

import cn.hutool.core.util.PageUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.Constants;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.*;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.CommentLike;
import com.tanhua.model.mongo.UserLike;
import com.tanhua.model.mongo.Video;
import com.tanhua.model.mongo.VideoLike;
import com.tanhua.model.vo.CommentVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VideoVo;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 小视频相关服务
 */
@Service
public class SmallVideoService {

    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private FastFileStorageClient client; //从调度服务器获取，一个目标存储服务器，上传
    @Autowired
    private FdfsWebServer webServer;// 获取存储服务器的请求URL
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private UserFreezeService userFreezeService;
    @Autowired
    private MqMessageService mqMessageService;


    @DubboReference
    private VideoApi videoApi;
    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private VideoLikeApi videoLikeApi;
    @DubboReference
    private CommentApi commentApi;
    @DubboReference
    private UserLikeApi userLikeApi;
    @DubboReference
    private CommentLikeApi commentLikeApi;


    public void uploadVideo(MultipartFile videoThumbnail, MultipartFile videoFile) {
        Long userId = UserHolder.getUserId();
        userFreezeService.checkUserStates(userId, Constants.USER_FREEZE_MOVEMENT);

        try {
            //获取视频文件后缀名
            String videoFileName = videoFile.getOriginalFilename();
            String extension = videoFileName.substring(videoFileName.lastIndexOf(".") + 1);
            //上传视频文件
            StorePath path = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), extension, null);
            String videoUrl = webServer.getWebServerUrl() + path.getFullPath();

            //上传图片
            String thumbnailName = videoThumbnail.getOriginalFilename();
            String picUrl = ossTemplate.upload(thumbnailName, videoThumbnail.getInputStream());

            Video video = new Video();
            video.setUserId(userId);
            video.setText(Constants.VIDEO_TEXT);
            video.setPicUrl(picUrl);
            video.setVideoUrl(videoUrl);
            video.setId(new ObjectId());
            videoApi.save(video);
            mqMessageService.sendLogMessage(userId, "0301", "video", video.getId().toHexString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取小视频列表
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult<VideoVo> getVideoList(Long page, Long pageSize) {
        Long userId = UserHolder.getUserId();
        String key = Constants.VIDEOS_RECOMMEND + userId;
        String redisVid = redisTemplate.opsForValue().get(key);
        Long total = 0L;
        Long start = (page - 1) * pageSize;
        int redisPage = 0;
        List<Video> videoList = new ArrayList<>();

        if(StringUtils.isNotEmpty(redisVid)) {
            String[] vidsArr = redisVid.split(",");
            total = Long.valueOf(vidsArr.length);
            redisPage = PageUtil.totalPage(total.intValue(), pageSize.intValue());
            if(total > start) {
                List<Long> vids = Arrays.stream(vidsArr).skip(start).limit(pageSize).map(Long::valueOf).collect(Collectors.toList());
                videoList = videoApi.getByVids(vids);
            }
        }

        if(CollectionUtils.isEmpty(videoList)) {
            PageResult<Video> pageResult = videoApi.findPage(userId,page - redisPage, pageSize);
            total += pageResult.getCounts();
            videoList = pageResult.getItems();
        }

        List<VideoVo> videoVos = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(videoList)) {
            List<Long> userIds = videoList.stream().map(Video::getUserId).collect(Collectors.toList());
            List<ObjectId> videoIds = videoList.stream().map(Video::getId).collect(Collectors.toList());
            //获取用户是否喜欢小视频
            Map<ObjectId, Boolean> videoLikeMap = videoLikeApi.getHasLikes(userId, videoIds);
            //获取用户信息列表
            Map<Long, UserInfo> userInfoMap = userInfoApi.getBatchIdsByCondition(userIds, null);
            videoVos = videoList.stream().map(video -> {
                UserInfo userInfo = userInfoMap.get(video.getUserId());
                VideoVo vo = VideoVo.init(userInfo, video);
                if(null != videoLikeMap.get(video.getId())) {
                    vo.setHasLiked(1);
                }
                if (userLikeApi.isLike(userId, video.getUserId())) {
                    vo.setHasFocus(1);
                }
                return vo;
            }).collect(Collectors.toList());
        }

        return new PageResult<>(page, pageSize, total, videoVos);
    }

    /**
     * 视频点赞
     * @param videoId
     */
    public Integer likeVideo(String videoId) {
        Long userId = UserHolder.getUserId();

        VideoLike videoLike = new VideoLike();
        videoLike.setUserId(userId);
        videoLike.setVideoId(new ObjectId(videoId));
        videoLike.setType(CommentType.LIKE.getType());
        Integer likeCount = videoLikeApi.like(videoLike);

        String key = Constants.VIDEO_INTERACT_KEY + videoId;
        String hashKey = Constants.VIDEO_LIKE_HASHKEY + userId;
        redisTemplate.opsForHash().put(key, hashKey, "1");
        mqMessageService.sendLogMessage(userId, "0302", "video", videoId);
        return likeCount;
    }

    /**
     * 视频-取消点赞
     * @param videoId
     */
    public Integer dislike(String videoId) {
        Long userId = UserHolder.getUserId();

        VideoLike videoLike = new VideoLike();
        videoLike.setUserId(userId);
        videoLike.setVideoId(new ObjectId(videoId));
        Integer likeCount = videoLikeApi.dislike(videoLike);

        String key = Constants.VIDEO_INTERACT_KEY + videoId;
        String hashKey = Constants.VIDEO_LIKE_HASHKEY + userId;
        redisTemplate.opsForHash().delete(key, hashKey);
        return likeCount;
    }

    /**
     * 获取视频评论列表
     * @param videoId
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult getComments(String videoId, Long page, Long pageSize) {
        VideoLike videoLike = new VideoLike();;
        videoLike.setVideoId(new ObjectId(videoId));
        videoLike.setType(CommentType.COMMENT.getType());

        PageResult<VideoLike> pageResult = videoLikeApi.getComments(videoLike, page, pageSize);
        List<VideoLike> videoLikes = pageResult.getItems();
        List<CommentVo> vos = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(videoLikes)) {
            List<Long> userIds = videoLikes.stream().map(VideoLike::getUserId).collect(Collectors.toList());
            List<String> commentIds = videoLikes.stream().map(vl -> vl.getId().toString()).collect(Collectors.toList());

            Map<Long, UserInfo> userInfoMap = userInfoApi.getBatchIdsByCondition(userIds, null);
            Map<ObjectId, Boolean> commentLikeMap = commentLikeApi.getHasLiked(UserHolder.getUserId(), commentIds);

            vos = videoLikes.stream().map(v -> {
                UserInfo userInfo = userInfoMap.get(v.getUserId());
                CommentVo vo = CommentVo.init(userInfo, v);
                if (null != commentLikeMap.get(v.getId())) {
                    vo.setHasLiked(1);
                }
                return vo;
            }).collect(Collectors.toList());
        }

        return new PageResult(page, pageSize, pageResult.getCounts(), vos);
    }

    /**
     * 发布视频评论
     * @param videoId
     * @param content
     */
    public void publishComments(String videoId, String content) {
        Long userId = UserHolder.getUserId();
        VideoLike videoLike = new VideoLike();
        videoLike.setUserId(userId);
        videoLike.setVideoId(new ObjectId(videoId));
        videoLike.setContent(content);
        videoLike.setType(CommentType.COMMENT.getType());

        videoLikeApi.publishComments(videoLike);
    }

    /**
     * 视频用户关注
     * @param focusUserId
     */
    public void userFocus(Long focusUserId) {
        UserLike userLike = new UserLike();
        userLike.setUserId(UserHolder.getUserId());
        userLike.setLikeUserId(focusUserId);
        userLike.setIsLike(true);
        userLikeApi.save(userLike);
    }

    /**
     * 视频用户取消关注
     * @param userUnFocusId
     */
    public void userUnFuces(Long userUnFocusId) {
        UserLike userLike = new UserLike();
        userLike.setUserId(UserHolder.getUserId());
        userLike.setLikeUserId(userUnFocusId);
        userLike.setIsLike(false);
        userLikeApi.save(userLike);
    }

    /**
     * 评论点赞
     * @param id
     */
    public Integer commentLike(String id) {
        CommentLike commentLike = new CommentLike();
        commentLike.setUserId(UserHolder.getUserId());
        commentLike.setCommentId(id);
        return commentLikeApi.saveVideoCommentLike(commentLike);
    }

    /**
     * 评论取消点赞
     * @param commentId
     * @return
     */
    public Integer commentDislike(String commentId) {
        CommentLike commentLike = new CommentLike();
        commentLike.setUserId(UserHolder.getUserId());
        commentLike.setCommentId(commentId);
        return commentLikeApi.removeVideoCommentLike(commentLike);
    }
}
